package com.kedacom.ctsp.authz.security.provider;

import com.kedacom.ctsp.serialize.ISerialization;
import com.kedacom.ctsp.serialize.SerializationException;
import com.kedacom.ctsp.serialize.SerializationUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.concurrent.TimeUnit;

/**
 * @author xuwei
 */
@Slf4j
public class RedisTokenManager extends TokenManager {

    private static final String REDIS_PREFIX = "security_token_";

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private ISerialization serialization;

    @Override
    public void addAccessToken(String accessToken, AuthUserDetails authUserDetails) {
        String serializedAuthUser = SerializationUtil.serializeToString(serialization, authUserDetails);
        String redisKey = getRedisKey(accessToken);
        redisTemplate.opsForValue().set(redisKey, serializedAuthUser, securityProperties.getExpireTime(), TimeUnit.MINUTES);
    }

    @Override
    public void removeAccessToken(String accessToken) {
        String redisKey = getRedisKey(accessToken);
        redisTemplate.delete(redisKey);
    }

    @Override
    public boolean existAccessToken(String accessToken) {
        if (StringUtils.isBlank(accessToken)) {
            return false;
        }
        return redisTemplate.hasKey(getRedisKey(accessToken));
    }

    @Override
    public AuthUserDetails getAuthUserDetailsByAccessToken(String accessToken) {
        if (StringUtils.isBlank(accessToken)) {
            return null;
        }
        String redisKey = getRedisKey(accessToken);
        String data = redisTemplate.opsForValue().get(redisKey);
        if (StringUtils.isBlank(data)) {
            return null;
        }
        try {
            return SerializationUtil.deserialize(serialization, data, AuthUserDetails.class);
        } catch (SerializationException e) {
            log.warn("accessToken{}'s data cannot be deserialized.", accessToken);
            return null;
        }
    }

    private String getRedisKey(String accessToken) {
        return REDIS_PREFIX + accessToken;
    }

    @Override
    protected void refreshToken(String accessToken) {
        String redisKey = getRedisKey(accessToken);
        redisTemplate.expire(redisKey, securityProperties.getExpireTime(), TimeUnit.MINUTES);
    }


}